package common

import (
	_ "./odbc"
	"database/sql"
	"fmt"
	"os"
	"reflect"
)

var (
	ConnectString string
	Prd01         string
	Prd02         string
	Prd03         string
	Prd05         string
	Prd06         string
)

func FetchAllRowsPtr(query, conn string, struc interface{}, cond ...interface{}) *[]interface{} {
	db, err := sql.Open("odbc", conn)
	if err != nil {
		Application.SendMail(fmt.Sprintf("sql.Open Error: %v\n", err))
		panic(err)
	}
	defer db.Close()

	stmt, err := db.Prepare(query)
	if err != nil {
		Application.SendMail(fmt.Sprintf("db.Prepare Error: %v\n", err))
		panic(err)
	}
	defer stmt.Close()

	rows, err := stmt.Query(cond...)
	if err != nil {
		Application.SendMail(fmt.Sprintf("stmt.Query Error: %v\n", err))
		panic(err)
	}
	defer rows.Close()

	result := make([]interface{}, 0)
	s := reflect.ValueOf(struc).Elem()
	leng := s.NumField()
	onerow := make([]interface{}, leng)
	for i := 0; i < leng; i++ {
		onerow[i] = s.Field(i).Addr().Interface()
	}
	for rows.Next() {
		err = rows.Scan(onerow...)
		if err != nil {
			Application.SendMail(fmt.Sprintf("Error: %v\nQuery: %v\nCondition: %v\n", err, query, cond))
			panic(err)
		}
		result = append(result, s.Interface())
	}

	return &result
}

func FetchOneRowPtr(query, conn string, struc interface{}, cond ...interface{}) *interface{} {
	db, err := sql.Open("odbc", conn)
	if err != nil {
		Application.SendMail(fmt.Sprintf("sql.Open Error: %v\n", err))
		panic(err)
	}
	defer db.Close()

	stmt, err := db.Prepare(query)
	if err != nil {
		Application.SendMail(fmt.Sprintf("db.Prepare Error: %v\n", err))
		panic(err)
	}
	defer stmt.Close()

	row := stmt.QueryRow(cond...)
	s := reflect.ValueOf(struc).Elem()
	leng := s.NumField()
	onerow := make([]interface{}, leng)
	for i := 0; i < leng; i++ {
		onerow[i] = s.Field(i).Addr().Interface()
	}
	err = row.Scan(onerow...)
	if err != nil && err != sql.ErrNoRows {
		switch s.Interface().(type) {
		case SPReturn:
			flg, chn, eng := s.Interface().(SPReturn).Flag, s.Interface().(SPReturn).ChnMsg, s.Interface().(SPReturn).EngMsg
			Application.SendMail(fmt.Sprintf("Error: %v\nQuery: %v\nCondition: %v\nFlag: %d\nCHN: %s, Leng: %d\nENG: %s, Leng: %d\n", err, query, cond, flg, chn, len(chn), eng, len(eng)))
			fmt.Fprintf(os.Stdout, "Error: %v\nQuery: %v\nCondition: %v\nFlag: %d\nCHN: %s, Leng: %d\nENG: %s, Leng: %d\n", err, query, cond, flg, chn, len(chn), eng, len(eng))
		default:
			Application.SendMail(fmt.Sprintf("Error: %v\nQuery: %v\nCondition: %v\n", err, query, cond))
		}
		panic(err)
	}
	result := s.Interface()

	return &result
}

func ExecSqlNonRst(query, conn string, cond ...interface{}) error {
	db, err := sql.Open("odbc", conn)
	if err != nil {
		Application.SendMail(fmt.Sprintf("sql.Open Error: %v\n", err))
		panic(err)
	}
	defer db.Close()

	stmt, err := db.Prepare(query)
	if err != nil {
		Application.SendMail(fmt.Sprintf("db.Prepare Error: %v\n", err))
		panic(err)
	}
	defer stmt.Close()

	_, err = stmt.Exec(cond...)
	if err != nil {
		Application.SendMail(fmt.Sprintf("Error: %v\nQuery: %v\nCondition: %v\n", err, query, cond))
		panic(err)
	}

	return nil
}

func GetSqlTransaction(conn string) *sql.Tx {
	db, err := sql.Open("odbc", conn)
	if err != nil {
		Application.SendMail(fmt.Sprintf("sql.Open Error: %v\n", err))
		panic(err)
	}
	defer db.Close()

	tx, err := db.Begin()
	if err != nil {
		Application.SendMail(fmt.Sprintf("Error: %v\n", err))
		panic(err)
	}
	return tx
}
